package uk.ac.glasgow.oose2.gcf.model;
/**

 * A basic Reverse Polish Notation Calculator for operations on Double values
 * 
 * <p>Assume the top of the this is y, and the next element is x. </p>
 * 
 * <p>The following arithmetic operations are supported:</p>
 * 
 * <ul>
 *  <li>plus   replace x and y by x+y </li>
 *  <li>minus  replace x and y by x-y </li>
 *  <li>times  replace x and y by x*y </li>
 *  <li>divide replace x and y by x/y </li>
 *  <li>sign    replaces y by -y </li>
 *  <li>invert  replaces y by 1/y </li>
 *  <li>square  replaces y by y*y </li>
 *  <li>sqrt    replaces y by sqrt(y) </li>
 * </ul>
 * 
 * <p>The following accumulator operations are supported:</p>
 * 
 * <ul>
 *  <li>aClear  clear Accumulator[y]; replace y by value of Accumulator[y]  </li>
 *  <li>aRecall replace y by Accumulator[y] </li>
 *  <li>accPlus  add x to Accumulator<y>, leaving x on top of this </li>
 *  <li>accStore set Accumulator<y> to x, leaving x on top of this </li>
 * </ul>
 * 
 * @author J Sventek
 * @author tws
 * @version $Id:$
 * 
 */
import uk.ac.glasgow.oose2.gcf.model.operation.acc.impl.AccClear;
import uk.ac.glasgow.oose2.gcf.model.operation.acc.impl.AccPlus;
import uk.ac.glasgow.oose2.gcf.model.operation.acc.impl.AccRecall;
import uk.ac.glasgow.oose2.gcf.model.operation.acc.impl.AccStore;
import uk.ac.glasgow.oose2.gcf.model.operation.stack.math.impl.Add;
import uk.ac.glasgow.oose2.gcf.model.operation.stack.math.impl.Divide;
import uk.ac.glasgow.oose2.gcf.model.operation.stack.math.impl.Invert;
import uk.ac.glasgow.oose2.gcf.model.operation.stack.math.impl.Minus;
import uk.ac.glasgow.oose2.gcf.model.operation.stack.math.impl.Pi;
import uk.ac.glasgow.oose2.gcf.model.operation.stack.math.impl.Sign;
import uk.ac.glasgow.oose2.gcf.model.operation.stack.math.impl.Sqrt;
import uk.ac.glasgow.oose2.gcf.model.operation.stack.math.impl.Square;
import uk.ac.glasgow.oose2.gcf.model.operation.stack.math.impl.Time;

public class BasicCalculator extends RPNCalculator<Double>{
	
	/** A constant close to zero used for testing results of divisions */
	public static final double SMALL_DOUBLE = 1.0e-300;
		
	/**
	 * create an empty basic calculator
	 */
	public BasicCalculator() {
		super();
	}
	
	/**
	 * Convenience method for pushing string representations of double values onto
	 * the calculator
	 * @param d the string representation of a Double value to be pushed onto the stack
	 * @throws CalculatorException if the String is not a legal double
	 */
	public void enter (String d) throws CalculatorException{
		enter(Double.valueOf(d));
	}
	
	//arithmetic operations - provides a facade to the registered operations
	
	/** replace the top two elements of the stack by their sum */
	public void plus() throws CalculatorException {new Add(stack).invoke();}
	
	/** replace the top two elements of the stack by their difference */
	public void minus() throws CalculatorException {new Minus(stack).invoke();}
	
	/** replace the top two elements of the stack by their product */
	public void times() throws CalculatorException {new Time(stack).invoke();}
	
	/** replace the top two elements of the stack by their quotient */
	public void divide() throws CalculatorException {new Divide(stack).invoke();}
	
	/** replace top element by -(top element) */
	public void sign() throws CalculatorException {new Sign(stack).invoke();}
	
	/** replace top element by 1/(top element) */
	public void invert() throws CalculatorException {new Invert(stack).invoke();}
	
	/** replace the top element of the stack by its square */
	public void square() throws CalculatorException {new Square(stack).invoke();}
	
	/** replace the top element of the stack by its positive square root */
	public void sqrt() throws CalculatorException {new Sqrt(stack).invoke();}
	
	/** push the constant pi onto the top element of the stack */
	public void pi() throws CalculatorException {new Pi(stack).invoke();}
			
	//Accumulator operations.
	
	/**
	 * replace index on the stack by value of accumulator with that index AFTER
	 * THE ACCUMULATOR HAS BEEN CLEARED (0.0)
	 */
	public void Aclear() throws CalculatorException {new AccClear(stack,accumulators).invoke();}
	
	/** replace index on the stack by value of accumulator with that index */
	public void Arecall() throws CalculatorException {new AccRecall(stack,accumulators).invoke();}

	/** add x to accumulator indexed by y, leaving x on top of the stack */
	public void Aplus() throws CalculatorException {new AccPlus(stack,accumulators).invoke();}

	/** replace value of accumulator indexed by y with x, leave x on top of this*/
	public void Astore() throws CalculatorException {new AccStore(stack,accumulators).invoke();}


}